package com.example.yupao.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.yupao.common.BaseResponse;
import com.example.yupao.common.ErrorCode;
import com.example.yupao.common.ResultUtils;
import com.example.yupao.exception.BusinessException;
import com.example.yupao.model.domain.Team;
import com.example.yupao.model.domain.User;
import com.example.yupao.model.domain.UserTeam;
import com.example.yupao.model.dto.TeamQuery;
import com.example.yupao.model.request.*;
import com.example.yupao.model.vo.TeamUserVO;
import com.example.yupao.service.UserService;
import com.example.yupao.service.UserTeamService;
import com.example.yupao.service.TeamService;
import io.swagger.annotations.Api;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;


/**
 * 队伍接口
 *
 * @author baoerjie
 */

//@CrossOrigin(origins = {"http://localhost:3000/"}, allowCredentials = "true")
//@CrossOrigin(origins = {"http://119.23.70.68:3000/"}, allowCredentials = "true")
@CrossOrigin(origins = {"http://119.23.70.68:3000/"},allowCredentials="true",allowedHeaders = "*",methods = {POST,GET})
//@CrossOrigin(origins = {"http://localhost:3000/"})
@RestController // 等价于 @ResponseBody + @Controller
@RequestMapping("/team")
@Api(tags = "1.队伍管理模块")
@Slf4j
public class TeamController {

    @Resource
    private UserService userService;

    @Resource
    private TeamService teamService;

    @Resource
    private UserTeamService userTeamService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 创建队伍
     * @param teamAddRequest
     * @param request
     * @return
     */
    @PostMapping("/add")
    public BaseResponse<Long> addTeam(@RequestBody TeamAddRequest teamAddRequest, HttpServletRequest request){
        if (teamAddRequest == null){
            throw new BusinessException(ErrorCode.NUll_ERROR);
        }
        Team team = new Team();
        BeanUtils.copyProperties(teamAddRequest, team); // 这个就是把teamAddRequest 中的属性赋值给team, 不用一个一个的set了
        User loginUser = userService.getLoginUser(request);
        long teamId = teamService.addTeam(team, loginUser);

        return ResultUtils.success(teamId);
    }

    /**
     * 更新队伍
     * @param teamUpdateRequest 前端可以传递的字段的封装类, 也就是team字段去掉一些不能修改的
     * @return
     */
    @PostMapping("/update")
    public BaseResponse<Boolean> updateTeam(@RequestBody TeamUpdateRequest teamUpdateRequest, HttpServletRequest request){
        if (teamUpdateRequest == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        boolean result = teamService.updateTeam(teamUpdateRequest, loginUser);
        if (!result){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"更新失败");
        }
        return ResultUtils.success(true);
    }

    /**
     * 查询
     * @param id
     * @return
     */
    @GetMapping("/get")
    public BaseResponse<Team> getTeamById(long id){
        if (id <= 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team team = teamService.getById(id);
        if (team == null){
            throw new BusinessException(ErrorCode.NUll_ERROR);
        }
        return ResultUtils.success(team);
    }


    /**
     * 查询队伍列表, 也就是所有的队伍信息
     * 附带判断   登录用户是否已经加入了查询中的某些队伍, 也就是用户加入了哪些队伍
     * @param teamQuery
     * @return
     */
    @GetMapping("/list")
    public BaseResponse<List<TeamUserVO>> listTeams(TeamQuery teamQuery, HttpServletRequest request) {
        if (teamQuery == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        boolean isAdmin = userService.isAdmin(request);
        // 1. 查询队伍列表
        // 没有附加条件, 就是查询所有队伍
        List<TeamUserVO> teamList = teamService.listTeams(teamQuery, isAdmin);
        // 拿到所有队伍的 id
        List<Long> teamIdList = teamList.stream()
                .map(teamUserVO -> teamUserVO.getId()).collect(Collectors.toList());
        ///////////////////注意这里的 id 有可能为空, 注意

        // 2. 判断当前用户是否已加入队伍
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        try{
            // 先查询登录用户加入了哪些队伍
            User loginUser = userService.getLoginUser(request);
            userTeamQueryWrapper.eq("userId", loginUser.getId());
            userTeamQueryWrapper.in("teamId", teamIdList);
            // 当前登录用户所加入的队伍
            List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
            // 拿出来队伍id
            // 已加入队伍的id集合2
            List<Long> hasJoinTeamIdSet = userTeamList.stream()
                    .map(userTeam -> userTeam.getTeamId()).collect(Collectors.toList());
            // 设置一下TeamUserVO里的字段: 是否加入到该队伍
            // 遍历所有的队伍id集合, 如果 已加入队伍的id集合2 里也有这个id, 就把这个字段设为已加入
            // teamList 里的对象都是 TeamUserVO 类型的
            teamList.forEach( teamUserVO -> {
                // 如果包含了就设置为 true, 没有就是 false
                boolean hasJoin = hasJoinTeamIdSet.contains(teamUserVO.getId());
                teamUserVO.setHasJoin(hasJoin);
            });
        }catch (Exception e){
            log.error("查询队伍信息错误, 可能未登录", e);
        }

        // 3、查询已加入队伍的人数
        return getListCount(teamList, teamIdList);
    }

    private BaseResponse<List<TeamUserVO>> getListCount(List<TeamUserVO> teamList, List<Long> teamIdList) {
        QueryWrapper<UserTeam> userTeamJoinQueryWrapper = new QueryWrapper<>();
        userTeamJoinQueryWrapper.in("teamId", teamIdList);
        List<UserTeam> userTeamList = userTeamService.list(userTeamJoinQueryWrapper);
        // 队伍 id => 加入这个队伍的用户列表.  根据队伍id进行分组 key 是队伍id, value 是用户的列表, 不一定是一个
        Map<Long, List<UserTeam>> teamIdUserTeamList = userTeamList.stream().collect(Collectors.groupingBy(UserTeam::getTeamId));
        // 设置字段, 一个队伍有多少人. 也就是先得到 value, 是每个队伍中有多少人. .size() 就是数量.  假如一个队伍中的用户列表是空的, 我们默认设置为一个空数组, 人数就是0
        teamList.forEach(team -> team.setHasJoinNum(teamIdUserTeamList.getOrDefault(team.getId(), new ArrayList<>()).size()));
        return ResultUtils.success(teamList);
    }
    // 换成上面的我们自己查询
//    @GetMapping("/list")
//    public BaseResponse<List<Team>> listTeams(TeamQuery teamQuery) {
//        if (teamQuery == null) {
//            throw new BusinessException(ErrorCode.PARAMS_ERROR);
//        }
//        Team team = new Team();
//        // 注意这里的BeanUtils 是 spring的
//        BeanUtils.copyProperties(team, teamQuery);
//        QueryWrapper<Team> queryWrapper = new QueryWrapper<>(team);
//        List<Team> teamList = teamService.list(queryWrapper);
//        return ResultUtils.success(teamList);
//    }

    /**
     *  获取我创建的队伍信息
     * @param teamQuery
     * @param request
     * @return
     */
    @GetMapping("/list/my/create")
    public BaseResponse<List<TeamUserVO>> listMyCreateTeams(TeamQuery teamQuery, HttpServletRequest request) {
        if (teamQuery == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        // 判断是不是管理员
//        boolean isAdmin = userService.isAdmin(request);
        // 这里可以复用之前查队伍的接口, 只用设置一下条件, 创建人userId == loginUserId
        teamQuery.setUserId(loginUser.getId());
        // 此处传递 true, 确保是管理员, 也就是自己能看到自己创建的队伍, 无论是私密还是加密的
        List<TeamUserVO> teamList = teamService.listTeams(teamQuery, true);
        // ------------------------------
        // 添加一下查询私密的和加密的
        teamQuery.setStatus(1);
        List<TeamUserVO> teamUserVOList = teamService.listTeams(teamQuery, true);
        teamList.addAll(teamUserVOList);
        // 查询加密的
        teamQuery.setStatus(2);
        List<TeamUserVO> teamUserVOList2 = teamService.listTeams(teamQuery, true);
        teamList.addAll(teamUserVOList2);

        // 拿到所有队伍的 id
        List<Long> teamIdList = teamList.stream()
                .map(teamUserVO -> teamUserVO.getId()).collect(Collectors.toList());
        // 这个就是用于求队伍中有多少人数
        getListCount(teamList, teamIdList);

        return ResultUtils.success(teamList);
    }

    /**
     *  获取我已加入的队伍信息
     * @param teamQuery
     * @param request
     * @return
     */
    @GetMapping("/list/my/join")
    public BaseResponse<List<TeamUserVO>> listMyJoinTeams(TeamQuery teamQuery, HttpServletRequest request) {
        if (teamQuery == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        // 判断是不是管理员
//        boolean isAdmin = userService.isAdmin(request);
        // 先去关系表中查询出所有的 队伍id
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", loginUser.getId());
        // teamId, userId 关系表中userId 是加入的用户的id, 不是创始人
        // 1  2
        // 1  3
        // 2  3
        // 查出之后就是
        // 1 => 2 、3
        // 2 => 3
        // 其实查出来的 对应关系就是一对一的, 但是为了防止数据有错误导致查出来的 teamId 有重复的, 所以还是要把 teamId 去一下重
        List<UserTeam> userTeamList = userTeamService.list(queryWrapper);

        Map<Long, List<UserTeam>> listMap = userTeamList.stream().
                collect(Collectors.groupingBy(UserTeam::getTeamId));
        Set<Long> longSet = listMap.keySet(); // 取出所有的 teamId, 也就是 key
        ArrayList<Long> idList = new ArrayList<>(longSet);
        teamQuery.setIdList(idList);

        // 调用查询service层, 查找符合要求的队伍
        List<TeamUserVO> teamUserVOList = teamService.listTeams(teamQuery, true);


        // 添加一下查询私密的和加密的
        teamQuery.setStatus(1);
        List<TeamUserVO> teamUserVOList3 = teamService.listTeams(teamQuery, true);
        teamUserVOList.addAll(teamUserVOList3);

        teamQuery.setStatus(2);
        List<TeamUserVO> teamUserVOList2 = teamService.listTeams(teamQuery, true);
        teamUserVOList.addAll(teamUserVOList2);

        // 6.22 自己新加, 鱼皮里没加---------------------------------------------------
        for (TeamUserVO teamUserVO : teamUserVOList)
            teamUserVO.setHasJoin(true);

        // 拿到所有队伍的 id
        List<Long> teamIdList = teamUserVOList.stream()
                .map(teamUserVO -> teamUserVO.getId()).collect(Collectors.toList());
        // 这个就是用于求队伍中有多少人数
        getListCount(teamUserVOList, teamIdList);

        return ResultUtils.success(teamUserVOList);
    }


    /**
     * 分页查询
     * @param teamQuery
     * @return
     */
    @GetMapping("/list/page")
    public BaseResponse<Page<Team>> listTeamsByPage(TeamQuery teamQuery) {
        if (teamQuery == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team team = new Team();
        BeanUtils.copyProperties(teamQuery, team);
        Page<Team> page = new Page<>(teamQuery.getPageNum(),teamQuery.getPageSize());
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>(team);
        Page<Team> resultPage = teamService.page(page,queryWrapper);
        return ResultUtils.success(resultPage);
    }


    /**
     * 加入队伍
     * @param teamJoinRequest
     * @param request
     * @return
     */
    @PostMapping("/join")
    public BaseResponse<Boolean> joinTeam(@RequestBody TeamJoinRequest teamJoinRequest, HttpServletRequest request){
        // 先判断参数
        if (teamJoinRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "前端请求的参数为空");
        }

        User loginUser = userService.getLoginUser(request);
        boolean result = teamService.joinTeam(teamJoinRequest, loginUser);
        return ResultUtils.success(result);
    }

    /**
     * 退出队伍
     * @param teamQuitRequest
     * @param request
     * @return
     */
    @PostMapping("/quit")
    public BaseResponse<Boolean> quitTeam(@RequestBody TeamQuitRequest teamQuitRequest, HttpServletRequest request){
        // 先判断参数
        if (teamQuitRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "前端请求的参数为空");
        }

        User loginUser = userService.getLoginUser(request);
        boolean result = teamService.quitTeam(teamQuitRequest, loginUser);
        return ResultUtils.success(result);
    }


    /**
     * 队长解散队伍
     * @param deleteRequest
     * @return
     */
    @PostMapping("/delete")
    public BaseResponse<Boolean> deleteTeam(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.NUll_ERROR);
        }
        long teamId = deleteRequest.getId();
        User loginUser = userService.getLoginUser(request);
        boolean result = teamService.deleteTeam(teamId, loginUser);
        if (!result) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除失败");
        }
        return ResultUtils.success(true);
    }

}
